﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Controls.LiveControl
{
    public partial class GdiScreen : Control
    {
        private Bitmap Screen { get; set; }
        private ScreenStatus _screenStatus;
        public GdiScreen()
        {
            InitializeComponent();

            Screen = new Bitmap(1, 1);
            _screenStatus = ScreenStatus.FullScreen;

            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);

        }

        private Rectangle _srcRectangle;
        public void OnlyShowProc(Rectangle srcRectangle, ScreenStatus status)
        {
            _srcRectangle = srcRectangle;
            if (_screenStatus != status)
            {
                _screenStatus = status;
                this.Invalidate();
            }
        }

        public void ShowFullScreen()
        {
            _screenStatus = ScreenStatus.FullScreen;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            switch (_screenStatus)
            {
                case ScreenStatus.FullScreen:
                    e.Graphics.DrawImage(Screen, new Rectangle(Point.Empty, this.Size));
                    break;
                case ScreenStatus.OnlyShowProcAndFit:
                    e.Graphics.DrawImage(Screen, new Rectangle(Point.Empty, this.Size), _srcRectangle, GraphicsUnit.Pixel);
                    break;
                case ScreenStatus.OnlyShowProcNotFit:
                    e.Graphics.FillRectangle(Brushes.Gray, new Rectangle(Point.Empty, this.Size));

                    e.Graphics.DrawImage(Screen, GetScreenRectangle(_srcRectangle), _srcRectangle, GraphicsUnit.Pixel);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

        }

        private RectangleF GetScreenRectangle(Rectangle srcRectangle)
        {
            var ratioX = Width/(float) Screen.Width;
            var ratioY = Height/(float) Screen.Height;
            var retRect = new RectangleF(srcRectangle.X*ratioX, srcRectangle.Y*ratioY, srcRectangle.Width*ratioX,
                srcRectangle.Height*ratioY);
            return retRect;
        }
        

        private readonly Pen _pen = new Pen(Color.Magenta, 2.0f);

        public void Draw(Image image, Rectangle region, bool flagShowRegionOutlines = false)
        {
            if (Screen.Width * Screen.Height < region.Width * region.Height)
            {
                Screen = new Bitmap(region.Width, region.Height);
            }
            

            var gfx = Graphics.FromImage(Screen);
            //gfx.DrawImageUnscaled(image, region);
            GraphicsUnit unit = GraphicsUnit.Pixel;
            var retRect = new RectangleF(region.X, region.Y, region.Width,
                region.Height);
            gfx.DrawImage(image, retRect, image.GetBounds(ref unit), unit);

            if (flagShowRegionOutlines)
            {
                var gRegion = this.CreateGraphics();
                gRegion.DrawRectangle(_pen, region);
                gRegion.Dispose();
            }
            //this.Invalidate();
        }


        public MouseEventArgs ReAlignPos(MouseEventArgs e)
        {
            MouseEventArgs tMouseEventArgs;
            switch (_screenStatus)
            {
                case ScreenStatus.FullScreen:
                    return e;
                case ScreenStatus.OnlyShowProcAndFit:
                    tMouseEventArgs = e;
                    break;
                case ScreenStatus.OnlyShowProcNotFit:
                    tMouseEventArgs = GetNotFitAlign(e);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }


            return tMouseEventArgs;
        }

        private MouseEventArgs GetNotFitAlign(MouseEventArgs mouseEventArgs)
        {
            return mouseEventArgs;
        }

        public void SetRect(Rectangle bounds)
        {
            Bitmap tempScreen = Screen;
            Screen = new Bitmap(bounds.Width, bounds.Height);
            tempScreen.Dispose();
        }
    }
}
